package com.example.learndevice.widget

import android.content.Context
import android.graphics.*
import android.hardware.Camera
import android.util.AttributeSet
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import com.example.learndevice.util.BitmapUtil
import com.example.learndevice.util.MediaUtil
import com.example.learndevice.util.MetricsUtil
import com.example.learndevice.util.Utils
import java.io.ByteArrayOutputStream
import java.lang.Exception

/**
 *
 * @Author： LJH
 * @Time： 2022/7/6
 * @description：
 */
class CameraView(context: Context,attr:AttributeSet):SurfaceView(context,attr) {
    companion object{
        @JvmField
        val CAMERA_BEHIND = 0
        @JvmField
        val CAMERA_FRONT = 1
        @JvmField
        val TAG = "CameraView"
    }
    private var mCamera:Camera? = null
    private lateinit var mHolder: SurfaceHolder
    private var isPreviewing = false
    private lateinit var mCameraSize:Point
    private var mCameraType = CAMERA_BEHIND

    fun setCameraType(cameraType:Int){
        mCameraType = cameraType
    }

    fun getCameraType():Int{
        return mCameraType
    }

    //下面是单拍的代码
    //照片的保存路径
    private var mPhotoPath = ""

    /**
     * 获取照片的保存路径
     * @return String
     */
    fun getPhotoPath():String{
        return mPhotoPath
    }

    fun doTakePicture(){
        if (isPreviewing && mCamera != null){
            //命令相机拍摄一张照片
            mCamera?.takePicture(mShutterCallback(),null,mPictureCallback)
        }
    }

    //获得拍照图片的回调。在此保存图片
    private val mPictureCallback = object :Camera.PictureCallback{
        override fun onPictureTaken(data: ByteArray?, camera: Camera?) {
            Log.d(TAG,"onPictureTaken...")
            var raw:Bitmap? = null
            if (data != null){
                //原始图像数据data是字节数组，需要将其解析成位图
                raw = BitmapFactory.decodeByteArray(data,0,data?.size)//data是字节数据，将其解析成位图
                //停止预览画面
                mCamera?.stopPreview()
                isPreviewing = false
            }
            //旋转位图
            val bitmap = BitmapUtil.getRotateBitmap(raw,if (mCameraType == CAMERA_BEHIND) 90F else -90F)
            //获取本次拍摄的照片保存路径
            mPhotoPath = "${BitmapUtil.getCachePath(context)}${Utils.getNowDateTimeFull()}.jpg"
            //保存文件照片
            BitmapUtil.saveBitmap(mPhotoPath,bitmap,"jpg",80)
            Log.d(TAG,"bitmap.size = ${bitmap.byteCount/1024}K,path=${mPhotoPath}")
            try {
                //保存文件需要时间
                Thread.sleep(1000)
            }catch (e:InterruptedException){
                e.printStackTrace()
            }
            //再次进入预览
            mCamera?.startPreview()
            isPreviewing = true
        }
    }

    //快门按下的回调，在这里可以设置类似播放“咔嚓”声之类的操作。默认的就是咔嚓。
    private fun mShutterCallback():Camera.ShutterCallback = object : Camera.ShutterCallback{
        override fun onShutter() {
            Log.d(TAG,"onShutter...")
        }
    }

    //预览画面状态变更时的回调
    private val mSurfaceCallback:SurfaceHolder.Callback = object :SurfaceHolder.Callback{
        //在表面视图创建时触发
        override fun surfaceCreated(holder: SurfaceHolder) {
            // 当预览视图创建的时候开启相机
            mCamera = Camera.open(mCameraType)
            try {
                // 设置预览
                mCamera?.setPreviewDisplay(holder)
                mCameraSize = MetricsUtil.getCameraSize(mCamera?.parameters,MetricsUtil.getSize(context))
                Log.d(TAG,"width=${mCameraSize.x},height=${mCameraSize.y}")
                val parameters = mCamera?.parameters
                //设置预览大小
                parameters?.setPreviewSize(mCameraSize.x,mCameraSize.y)
                //设置图片保存时大小
                parameters?.setPictureSize(mCameraSize.x,mCameraSize.y)
                //设置格式
                parameters?.setPictureFormat(ImageFormat.JPEG)
                // 设置自动对焦。前置摄像头似乎无法自动对焦
                if (mCameraType == CAMERA_BEHIND){
                    parameters?.focusMode = (Camera.Parameters.FOCUS_MODE_AUTO)
                }
                mCamera?.parameters = parameters
            } catch (e:Exception){
                e.printStackTrace()
                //遇到异常需要释放相机资源
                mCamera?.release()
                mCamera = null
            }
        }

        //在表面视图变更时触发
        override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
            //设置相机的展示角度
            mCamera?.setDisplayOrientation(90)
            //开始预览画面
            mCamera?.startPreview()
            isPreviewing = true
            //开始自动对焦
            mCamera?.autoFocus(null)
            //这里的setPreviewCallback给连拍使用
            //设置相机的预览监听器
            mCamera?.setPreviewCallback(mPreviewCallback)
        }

        //在表面视图销毁时触发
        override fun surfaceDestroyed(holder: SurfaceHolder) {
            //将预览监听置空
            mCamera?.setPreviewCallback(null)
            //停止预览画面
            mCamera?.stopPreview()
            //释放相机资源
            mCamera?.release()
            mCamera = null
        }
    }

    init {
        //获取表面视图的表面持有者
        mHolder = holder
        //去除黑色背景。TRANSLUCENT半透明；TRANSPARENT透明
        mHolder.setFormat(PixelFormat.TRANSPARENT)
        //mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        //给表面持有者
        mHolder.addCallback(mSurfaceCallback)
    }
    // 下面是连拍的代码
    private var bShooting = false
    private var shootingNum = 0
    private lateinit var mShootArray:ArrayList<String>

    fun getShootingList():ArrayList<String>{
        Log.d(TAG,"mShootingArray.size() = ${mShootArray.size}")
        return mShootArray
    }

    fun doTakeShooting(){
        mShootArray = ArrayList<String>()
        bShooting = true
    }

    /**
     * 定义一个画面预览的回调监听器。在此捕获动态的连续图片
     */
    private val mPreviewCallback = object :Camera.PreviewCallback{
        override fun onPreviewFrame(data: ByteArray?, camera: Camera?) {
            Log.d(TAG,"onPreviewFrame bShooting=${bShooting},shooting_num=${shootingNum}")
            if (!bShooting){
                return
            }
            //获取相机的参数信息
            val parameters = camera?.parameters
            //获取预览数据的格式
            val imageFormat = parameters?.previewFormat
            val w = parameters?.previewSize?.width
            val h = parameters?.previewSize?.height
            val rect = Rect(0,0,w!!,h!!)
            //创建一个YUV格式的图像对象
            val yuvImg = YuvImage(data,imageFormat!!,w,h,null)
            try {
                val bos = ByteArrayOutputStream()
                yuvImg.compressToJpeg(rect,80,bos)
                //从字节数组中解析出位图数据
                val raw = BitmapFactory.decodeByteArray(bos.toByteArray(),0,bos.size())
                //旋转位图
                val bitmap = BitmapUtil.getRotateBitmap(raw,if(mCameraType == CAMERA_BEHIND) 90F else -90F)
                //获取本次拍摄的照片保存路径
                val path = "${BitmapUtil.getCachePath(context)}${Utils.getNowDateTimeFull()}.jpg"
                //把位图保存为图片文件
                BitmapUtil.saveBitmap(path,bitmap,"jpg",80)
                Log.d(TAG,"bitmap.size = ${bitmap.byteCount/1024}K,path=${path}")
                //再次进入预览画面
                camera.startPreview()
                shootingNum ++
                mShootArray.add(path)
                //每次连拍9张。
                if (shootingNum > 8){
                    bShooting = false
                }
            }catch (e:Exception){
                e.printStackTrace()
            }
        }
    }
}